﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Threading;
using Aga.Controls.Tree;
using Interpreter;

namespace LogoScriptIDE
{
    /// <summary>
    /// Interaction logic for WatchesWindow.xaml
    /// </summary>
    public partial class WatchesWindow : UserControl
    {

        public WatchesWindow()
        {
            InitializeComponent();
            m_varTable = new varTableModel();
            m_Changed = 0;
            ui_vartree.Model = m_varTable;
        }

        /// <summary>
        /// 保存当前的watches window中的变量
        /// </summary>
        private varTableModel m_varTable;

        /// <summary>
        /// 变量添加窗口
        /// </summary>
        private InputvarWindow m_inputvarWindow;

        /// <summary>
        /// 当m_Changed>0时表示需要update
        /// </summary>
        public int m_Changed;

        /// <summary>
        /// 判断当前是否有全局变量
        /// </summary>
        private bool global;

        /// <summary>
        /// 全局变量
        /// </summary>
        private Variable getG;

        /// <summary>
        /// 全局变量名
        /// </summary>
        private string getGname;

        /// <summary>
        /// 当变量为table时需要建立树状结构
        /// </summary>
        /// <param name="var">变量</param>
        /// <param name="level">深度</param>
        /// <returns>建立的树</returns>
        private ObservableCollection<Varforwatch> buildVartree(Variable var, int level)
        {
            // 树的层数不能超过255层，防止无穷递归调用建树
            if (level > 255) return null;
            ObservableCollection<Varforwatch> ans = new ObservableCollection<Varforwatch>();
            // 若全局变量与局部变量同时存在，则将全局变量作为局部变量的一个子成员来观察，在remark中会提示是全局变量
            if (global)
            {
                global = false;
                var p = new Varforwatch()
                {
                    Name = getGname,
                    Value = getG.ToString(null),
                    Type = VarType.getTypeString(getG.type),
                    Remark = "Global Variable"
                };
                if (getG.type == VarType.TYPE_TABLE)
                    if (buildVartree(getG, 0) != null)
                        p.Children = buildVartree(getG, 0);
                ans.Add(p);
            }
            if (var.type == VarType.TYPE_TABLE)
                foreach (var pair in var.table)
                {
                    string keyname;
                    if (pair.Key.type == VarType.TYPE_TABLE)
                    {
                        // 若key下标为table则调用table的toString
                        keyname = pair.Key.ToString(0);
                    }
                    else
                    {
                        if ((pair.Key.type == VarType.TYPE_C_FUNCTION)
                            || (pair.Key.type == VarType.TYPE_FUNCTION))
                        {
                            keyname = pair.Key.ToString(null);
                        }
                        else
                        {
                            // 不是则返回variable值
                            keyname = pair.Key.ToString(null);
                        }
                    }

                    // 新建观察变量
                    var p = new Varforwatch()
                    {
                        Name = keyname,
                        Value = pair.Value.ToString(null),
                        Type = VarType.getTypeString(pair.Value.type),
                        Remark = ""
                    };

                    // 若value是table则递归调用接着构造树
                    if (pair.Value.type == VarType.TYPE_TABLE)
                        p.Children = buildVartree(pair.Value, level + 1);

                    // 将此变量加入根结点
                    ans.Add(p);
                }
            return ans;
        }

        /// <summary>
        /// 刷新窗口
        /// </summary>
        /// <param name="m">虚拟机</param>
        public void Update(Machine m)
        {
            if (m_varTable == null)
                return;
            // 当程序调试执行或watches窗口有添加删除操作时更新
            if (m != null &&
                (m.Status == MachineStatus.MACHINE_STATUS_PAUSED ||
                m.Status == MachineStatus.MACHINE_STATUS_DEAD))
            {
                // 将watches中当前的变量更新一遍
                for (int j = 0; j < m_varTable.Root.Children.Count; j++)
                {
                    Varforwatch eachVar = m_varTable.Root.Children[j];

                    // 编译完成且变量名不为空，同时局部或全局变量中存在
                    if (m.CompileComplete && !string.IsNullOrEmpty(eachVar.Name) && (m.IsGlobalExists(eachVar.Name) || m.GetLocalIDByName(eachVar.Name) != -1))
                    {
                        Variable getV;
                        getGname = eachVar.Name;
                        global = m.IsGlobalExists(eachVar.Name);
                        int index = m.GetLocalIDByName(eachVar.Name);

                        if (global)
                            getG = m.GetGlobal(eachVar.Name);
                        else
                            getG = m.GetLocalByID(index);

                        // 若此变量名不存在局部变量则获取全局变量，若此变量名存在局部变量则显示局部变量的数据
                        if (index == -1)
                        {
                            getV = m.GetGlobal(eachVar.Name);
                            global = false;
                        }
                        else
                        {
                            getV = m.GetLocalByID(index);
                        }

                        // 将此变量的数据更新
                        eachVar.Value = getV.ToString(m);
                        eachVar.Remark = "Update successfully";
                        eachVar.Type = VarType.getTypeString(getV.type);

                        // 若为table或者全局与局部变量有同名情况 则需要构造树
                        if ((getV.type == VarType.TYPE_TABLE) || global)
                            eachVar.Children = buildVartree(getV, 0);
                    }
                    ui_vartree.Model = null;
                    ui_vartree.Model = m_varTable;
                }
            }
        }

        /// <summary>
        /// 添加变量回调函数
        /// </summary>
        private void ui_addVarClick(object sender, RoutedEventArgs e)
        {
            m_inputvarWindow = new InputvarWindow();
            FrameworkElement parent = Parent as FrameworkElement;
            while (parent.Parent != null) 
                parent = parent.Parent as FrameworkElement;
            m_inputvarWindow.Owner = parent as Window;
            m_inputvarWindow.ShowDialog();
            if (m_inputvarWindow.inputStatus() == 1)
                m_varTable.addVar(m_inputvarWindow.getVarname());
            m_Changed = 1;
        }

        /// <summary>
        /// 删除变量回调函数
        /// </summary>
        private void ui_delVarClick(object sender, RoutedEventArgs e)
        {
            var nodes = ui_vartree.SelectedNodes;
            List<int> indexes = new List<int>();
            foreach (var node in nodes)
            {
                if (node.Parent.Index == -1)
                    indexes.Add(node.Index); 
            }
            indexes.Sort();
            // 须按照从后往前的顺序删除
            for (int i = indexes.Count - 1; i >= 0; --i)
            {
                m_varTable.deleteVar(indexes[i]);
            }
        }
    }
}
